{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "import os\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "from torch.autograd import Variable\n",
    "import torch.utils.data as Data\n",
    "import torchvision\n",
    "import torch.nn.functional as F\n",
    "import numpy as np\n",
    "learning_rate = 1e-4\n",
    "keep_prob_rate = 0.7 #\n",
    "max_epoch = 3\n",
    "BATCH_SIZE = 50\n",
    "\n",
    "DOWNLOAD_MNIST = False\n",
    "if not(os.path.exists('./mnist/')) or not os.listdir('./mnist/'):\n",
    "    # not mnist dir or mnist is empyt dir\n",
    "    DOWNLOAD_MNIST = True\n",
    "\n",
    "\n",
    "train_data = torchvision.datasets.MNIST(root='./mnist/',train=True, transform=torchvision.transforms.ToTensor(), download=DOWNLOAD_MNIST,)\n",
    "train_loader = Data.DataLoader(dataset = train_data ,batch_size= BATCH_SIZE ,shuffle= True)\n",
    "\n",
    "test_data = torchvision.datasets.MNIST(root = './mnist/',train = False)\n",
    "test_x = Variable(torch.unsqueeze(test_data.test_data,dim  = 1),volatile = True).type(torch.FloatTensor)[:500]/255.\n",
    "test_y = test_data.test_labels[:500].numpy()\n",
    "\n",
    "class CNN(nn.Module):\n",
    "    def __init__(self):\n",
    "        super(CNN, self).__init__()\n",
    "        self.conv1 = nn.Sequential(\n",
    "            nn.Conv2d( # ???\n",
    "                # patch 7 * 7 ; 1  in channels ; 32 out channels ; ; stride is 1\n",
    "                # padding style is same(that means the convolution opration's input and output have the same size)\n",
    "                in_channels=      ,  \n",
    "                out_channels=     ,\n",
    "                kernel_size=      ,\n",
    "                stride=           ,\n",
    "                padding=          ,\n",
    "            ),\n",
    "            nn.ReLU(),        # activation function\n",
    "            nn.MaxPool2d(2),  # pooling operation\n",
    "        )\n",
    "        self.conv2 = nn.Sequential( # ???\n",
    "            # line 1 : convolution function, patch 5*5 , 32 in channels ;64 out channels; padding style is same; stride is 1\n",
    "            # line 2 : choosing your activation funciont\n",
    "            # line 3 : pooling operation function.\n",
    "            \n",
    "         \n",
    "\n",
    "        )\n",
    "        self.out1 = nn.Linear( 7*7*64 , 1024 , bias= True)   # full connection layer one\n",
    "\n",
    "        self.dropout = nn.Dropout(keep_prob_rate)\n",
    "        self.out2 = nn.Linear(1024,10,bias=True)\n",
    "\n",
    "\n",
    "\n",
    "    def forward(self, x):\n",
    "        x = self.conv1(x)\n",
    "        x = self.conv2(x)\n",
    "        x = x.view(      )  # flatten the output of coonv2 to (batch_size ,32 * 7 * 7)    # ???\n",
    "        out1 = self.out1(x)\n",
    "        out1 = F.relu(out1)\n",
    "        out1 = self.dropout(out1)\n",
    "        out2 = self.out2(out1)\n",
    "        output = F.softmax(out2)\n",
    "        return output\n",
    "\n",
    "\n",
    "def test(cnn):\n",
    "    global prediction\n",
    "    y_pre = cnn(test_x)\n",
    "    _,pre_index= torch.max(y_pre,1)\n",
    "    pre_index= pre_index.view(-1)\n",
    "    prediction = pre_index.data.numpy()\n",
    "    correct  = np.sum(prediction == test_y)\n",
    "    return correct / 500.0\n",
    "\n",
    "\n",
    "def train(cnn):\n",
    "    optimizer = torch.optim.Adam(cnn.parameters(), lr=learning_rate )\n",
    "    loss_func = nn.CrossEntropyLoss()\n",
    "    for epoch in range(max_epoch):\n",
    "        for step, (x_, y_) in enumerate(train_loader):\n",
    "            x ,y= Variable(x_),Variable(y_)\n",
    "            output = cnn(x)  \n",
    "            loss = loss_func(output,y)\n",
    "            optimizer.zero_grad()\n",
    "            loss.backward()\n",
    "            optimizer.step()\n",
    "            \n",
    "            if step != 0 and step % 20 ==0:\n",
    "                print(\"=\" * 10,step,\"=\"*5,\"=\"*5, \"test accuracy is \",test(cnn) ,\"=\" * 10 )\n",
    "\n",
    "if __name__ == '__main__':\n",
    "    cnn = CNN()\n",
    "    train(cnn)\n",
    "\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
